home *** CD-ROM | disk | FTP | other *** search
- // ContextWarrior
- // MacHack 97
- // Graham Herrick
- // this file is public domain
-
- #include <SetUpA4.h>
- #include <A4Stuff.h>
- #include <AppleGuide.h>
- #include <Speech.h>
- #include "ContextualMenu.h"
- #include "MoreFilesExtras.h"
-
- #define kInitID 128
- #define kCWFileMenuID 0x81
- #define kCWEditMenuID 0x82
- #define kCWSearchMenuID 0x83
- #define kCWProjectMenuID 0x85
- #define kCWWindowMenuID 0x84
- #define kCWHelpMenuID 0xBF96
-
- enum
- {
- kNowhere, // this goes to file menu
- kProjWindowContent, // map this to project menu
- kNormWindowContent, // map this to edit menu?
- kToolWindowContent, // this goes to search menu
- kWindowStructure // map this to window menu and/or file menu
- };
-
- typedef pascal void (*IMType)(void);
- typedef pascal long (*MSType)(Point pt);
-
- typedef struct
- {
- MenuHandle menuoH;
- short menuLeft;
- } MenuRec;
-
- typedef struct
- {
- short lastMenu,
- lastRight,
- mbResID;
- MenuRec menus[];
- } MenuList, *MenuListPtr, **MenuListHdl;
-
- void *gOldJGNE;
- IMType gOldInitMenus;
- MSType gOldMenuSelect;
- Boolean inJGNE;
- Boolean fakingAThing;
- Boolean hasCM,cmChecked,hasSpeech,speechChecked;
- long fakeResult;
- short oldMenuID;
- FSSpec gFileSpec;
- short helpStage;
- Str255 helpMess;
-
- pascal asm void myJGNE(void);
- pascal asm void NewInitMenusShell(void);
- pascal asm long NewMenuSelectShell(Point pt);
- long NewMenuSelect(Point pt);
- Boolean myGNE(EventRecord *event, Boolean preResult);
- MenuHandle GetCopyOfMenuWithThisID(short id, short newID);
- void NewInitMenus(void);
- Boolean ThisIsCodeWarrior(void);
- short WhereIsTheMouse(Point pt);
- void pStrCopy(StringPtr p1, StringPtr p2);
-
- void main(void)
- {
- long oldA4;
- Handle theInit = 0L;
- OSErr myErr;
- long result;
-
- oldA4 = SetCurrentA4();
- RememberA4();
- myErr = Gestalt(gestaltSystemVersion,&result);
- if(myErr || (LoWord(result) < 0x0800)) goto fail;
- theInit = Get1Resource('INIT',kInitID);
- if(!theInit) goto fail;
- fakingAThing = inJGNE = hasCM = cmChecked = hasSpeech = speechChecked = false;
- helpStage = 0;
- gFileSpec.name[0] = 0;
- gOldJGNE = LMGetGNEFilter();
- gOldInitMenus = (IMType)GetToolTrapAddress(_InitMenus);
- gOldMenuSelect = (MSType)GetToolTrapAddress(_MenuSelect);
- LMSetGNEFilter(myJGNE);
- SetToolTrapAddress((UniversalProcPtr)NewInitMenusShell,_InitMenus);
- SetToolTrapAddress((UniversalProcPtr)NewMenuSelectShell,_MenuSelect);
- DetachResource(theInit);
- goto exit;
- fail:
- SysBeep(10);
- SysBeep(10);
- SysBeep(10);
- if(theInit) ReleaseResource(theInit);
- exit:
- RestoreA4(oldA4);
- }
-
- pascal asm long NewMenuSelectShell(Point pt)
- {
- movem.l a0-a3/a6-a7/d0-d7,-(sp)
- JSR SetUpA4
- MOVE.L D0,D3 // res(4),pt(4),rtn(4),reg(38)
- MOVE.L 0x003C(sp),-(sp) // res(4),pt(4),rtn(4),reg(38),pt(4)
- JSR NewMenuSelect
- MOVE.L D0,d2 // res(4),pt(4),rtn(4),reg(38),pt(4)
- MOVE.L d3,D0
- EXG D0,A4
- addq.w #4,sp
- MOVE.L d2,0x0040(sp) // res(4),pt(4),rtn(4),reg(38)
- movem.l (sp)+,a0-a3/a6-a7/d0-d7 // res(4),pt(4),rtn(4)
- RTD #4
- }
-
- long NewMenuSelect(Point pt)
- {
- long result;
-
- if(ThisIsCodeWarrior() && fakingAThing && pt.v == 10 && pt.v == 10)
- {
- fakingAThing = false;
- result = fakeResult;
- }
- else result = gOldMenuSelect(pt);
- return result;
- }
-
- void NewInitMenus(void)
- {
- if (ThisIsCodeWarrior())
- {
- OSErr myErr;
- short mwRefNum = CurResFile();
- FSSpec dirSpec, gdirSpec;
- long gdparID;
- Boolean isDir;
-
- if(!speechChecked)
- {
- myErr = Gestalt(gestaltSpeechAttr,&gdparID);
- if (!myErr && (gdparID & (1<<gestaltSpeechMgrPresent))) hasSpeech = true;
- speechChecked = true;
- }
- if (!cmChecked)
- {
- myErr = Gestalt(gestaltContextualMenuAttr,&gdparID);
- if (!myErr && (gdparID & (1<<gestaltContextualMenuTrapAvailable))) hasCM = true;
- cmChecked = true;
- }
- if(hasCM)
- {
- InitContextualMenus();
- helpStage = 0;
- myErr = Gestalt(gestaltHelpMgrAttr,&gdparID);
- if (!myErr && (gdparID & (1<<gestaltAppleGuidePresent)))
- {
- myErr = FSpGetFileLocation(mwRefNum,&dirSpec);
- if(!myErr) myErr = FSMakeFSSpec(dirSpec.vRefNum,dirSpec.parID,
- "\p(CodeWarrior Guides)",&gdirSpec);
- if(!myErr) myErr = FSpGetDirectoryID(&gdirSpec,&gdparID,&isDir);
- if(!myErr) myErr = FSMakeFSSpec(gdirSpec.vRefNum,gdparID,
- "\pCodeWarrior IDE Guide",&gFileSpec);
- }
- }
- }
- }
-
- pascal asm void NewInitMenusShell(void)
- {
- movem.l a0-a3/a6-a7/d0-d7,-(sp)
- subq.w #4,sp
- jsr SetUpA4
- move.l d0,(sp)
- jsr NewInitMenus
- movea.l gOldInitMenus,a0
- jsr (a0)
- move.l (sp),d0
- exg d0,a4
- addq.w #4,sp
- movem.l (sp)+,a0-a3/a6-a7/d0-d7
- rts
- }
-
- pascal asm void myJGNE(void)
- {
- MOVE.L D0,A0 // save pre-result from SetUpA4
- JSR SetUpA4 // fix A4, stomp D0
- MOVE.L D0,-(A7) // save old A4
- MOVE.L A0,D0 // restore pre-result
- TST.B inJGNE // is myJGNE busy?
- BNE @1 // yes, so bail
- MOVE.B #true,inJGNE // mark myJGNE busy
- MOVE.W D0,-(A7) // push pre-result
- MOVE.L A1,-(A7) // push event record pointer
- JSR myGNE // do the real work
- MOVE.L (A7)+,A1 // restore event record pointer
- ADDQ.L #2,A7 // pop pre-result; post-result in D0
- ASL.W #8,D0 // bump C boolean to Lisa
- MOVE.W D0,8(A7) // stash result where caller expects it
- MOVE.B #false,inJGNE // mark myJGNE not busy
- @1:
- MOVE.L gOldJGNE,A0 // get previous jGNE
- MOVE.L (A7)+,A4 // restore A4
- cmp.l #0,a0
- beq bail
- MOVE.L A0,-(A7) // return to previous jGNE
- bail:
- RTS
- }
-
- Boolean myGNE(EventRecord *event, Boolean preResult)
- {
- Boolean postResult = preResult;
-
- if (preResult)
- {
- if (event->what == mouseDown || event->what == mouseUp && ThisIsCodeWarrior() &&
- cmChecked && hasCM)
- {
- if(IsShowContextualMenuClick(event))
- {
- MenuHandle fileMenu;
- short theID, place = WhereIsTheMouse(event->where);
-
- switch(place)
- {
- case kProjWindowContent: theID = kCWProjectMenuID; break;
- case kNormWindowContent: theID = kCWEditMenuID; break;
- case kWindowStructure: theID = kCWWindowMenuID; break;
- case kToolWindowContent: theID = kCWSearchMenuID; break;
- case kNowhere:
- default: theID = kCWFileMenuID; break;
- }
- fileMenu = GetCopyOfMenuWithThisID(theID,theID+5678);
-
- if(fileMenu)
- {
- unsigned long selType;
- short selMenuID;
- unsigned short selMenuItem;
- OSErr myErr;
-
- InsertMenu(fileMenu,hierMenu);
- if(helpStage>0 && helpStage<4)
- myErr = ContextualMenuSelect(fileMenu,event->where,false,
- kCMHelpItemOtherHelp,helpMess,0L,&selType,
- &selMenuID,&selMenuItem);
- else
- myErr = ContextualMenuSelect(fileMenu,event->where,false,
- kCMHelpItemAppleGuide,"\p",0L,&selType,
- &selMenuID,&selMenuItem);
- DeleteMenu(theID+5678);
- DisposeHandle((Handle)fileMenu);
- if (selMenuID==theID+5678) selMenuID = theID;
- if (!myErr && selType == kCMMenuItemSelected)
- {
- fakeResult = ((long)selMenuID << 16) & 0xFFFF0000;
- fakeResult |= (selMenuItem & 0x0000FFFF);
- fakingAThing = true;
- // should find a better way to put mouse in menu bar
- event->where.h = event->where.v = 10;
- }
- else if (!myErr && selType == kCMShowHelpSelected)
- {
- AGRefNum agRes;
-
- if(helpStage==0)
- {
- helpStage=1;
- pStrCopy("\pReal warriors don't need help",helpMess);
- if (hasSpeech) SpeakString(helpMess);
- }
- else if (helpStage==1)
- {
- helpStage++;
- pStrCopy("\pMaybe you're a virtual warrior",helpMess);
- if (hasSpeech) SpeakString(helpMess);
- }
- else if (helpStage==2)
- {
- helpStage++;
- pStrCopy("\pOr a CodePeacenik™",helpMess);
- if (hasSpeech) SpeakString(helpMess);
- }
- else if (helpStage==3)
- {
- helpStage++;
- pStrCopy("\pOkay. Here's some help.",helpMess);
- if (hasSpeech) SpeakString(helpMess);
- if (gFileSpec.name[0]) goto thing;
- }
- else if (gFileSpec.name[0])
- {
- thing:
- helpStage++;
- if(helpStage>15) helpStage = 0;
- switch(place)
- {
- case kProjWindowContent:
- myErr = AGOpenWithSearch(&gFileSpec,0,nil,"\pprojects",&agRes);
- break;
- case kWindowStructure:
- myErr = AGOpenWithSearch(&gFileSpec,0,nil,"\pcredits",&agRes);
- break;
- case kToolWindowContent:
- myErr = AGOpenWithSearch(&gFileSpec,0,nil,"\ptoolbar",&agRes);
- break;
- case kNormWindowContent:
- case kNowhere:
- default:
- myErr = AGOpenWithView(&gFileSpec,0,nil,kAGViewTopicAreas,&agRes);
- break;
- }
- }
- event->what = nullEvent;
- postResult = false;
- }
- else postResult = false;
- }
- }
- }
- }
- return postResult;
- }
-
- MenuHandle GetCopyOfMenuWithThisID(short id, short newID)
- {
- MenuListHdl theMList = (MenuListHdl)LMGetMenuList();
- short numMenus,i;
- MenuHandle aMenu;
-
- if(!theMList || !*theMList) return 0L;
- numMenus = (*theMList)->lastMenu/6;
- for(i=0;i<numMenus;i++)
- {
- aMenu = (*theMList)->menus[i].menuoH;
- if (aMenu && HandleZone((Handle)aMenu) && !MemError() && *aMenu && (*aMenu)->menuID == id)
- {
- HandToHand(&((Handle)aMenu));
- (*aMenu)->menuID = newID;
- return aMenu;
- }
- }
- return 0L;
- }
-
- Boolean ThisIsCodeWarrior(void)
- {
- return EqualString(LMGetCurApName(),"\pCodeWarrior IDE 2.0",true,true);
- }
-
- short WhereIsTheMouse(Point pt)
- {
- WindowPeek frontWind = (WindowPeek)LMGetWindowList();
-
- while(frontWind)
- {
- if(PtInRgn(pt,frontWind->strucRgn))
- {
- if(PtInRgn(pt,frontWind->contRgn))
- {
- Str255 title;
-
- if(frontWind->windowKind==0x4E21)
- return kNormWindowContent;
- GetWTitle((WindowPtr)frontWind,title);
- if(EqualString("\pToolbar",title,true,true))
- return kToolWindowContent;
- return kProjWindowContent;
- }
- return kWindowStructure;
- }
- frontWind = frontWind->nextWindow;
- }
- return kNowhere;
- }
-
- void pStrCopy(StringPtr p1, StringPtr p2)
- {
- BlockMoveData((Ptr)p1,(Ptr)p2,*p1+1);
- }
-
-
-